#ifndef	APP_GLOBALS_WORKFLOW
#define	APP_GLOBALS_WORKFLOW
#include <includes.h>

static void PORLocalRAMReset_WORKFLOW(void)
{

}
//WorkFlowTimingFreq 10hz
static uint8_t WorkflowTimerCounting(uint8_t TempWorkflow)
{
	uint8_t ActInform = DEF_FALSE;

    if (SMTimerCounter)
        SMTimerCounter--;
    
    if(CurrProcCountdownEnable)
        CurrProcCountdown++;
    else
        CurrProcCountdown=0;

	return (ActInform);
}
/* DstIn Request */
static uint8_t DstInRequestWorkLayerHandle(uint8_t TempWorkflow, uint8_t *ActInform)
{
	return (DEF_TRUE);
}


void ChangeGenWorkingSta(uint8_t GenWorkStaOrd_x,uint8_t OperaOpt)
{
    uint8_t state=DEF_TRUE;
    switch (GenWorkStaOrd_x)
    {
    case GenWorkStaOrd_Running:
        /* code */
        break;
    case GenWorkStaOrd_AlarmWarn:
        /* code */
        break;
    case GenWorkStaOrd_AlarmShutDown:
        // if(OperaOpt ==BitOperaOpt_Clr)
        // {
        //     if(GetFlagShareBufferDataContent(NULL,CfgOperaType_None,FlagShareBuffer_GenWorkingSta,GenWorkStaOrd_Running))
        //         state=DEF_FALSE;
        // }
        break;
    case GenWorkStaOrd_AlarmReset:
    case GenWorkStaOrd_ManualStart:
    case GenWorkStaOrd_AutoStart://运行中不允许更改流程
        if(GetFlagShareBufferDataContent(NULL,CfgOperaType_None,FlagShareBuffer_GenWorkingSta,GenWorkStaOrd_Running))
            state=DEF_FALSE;
        /* code */
        break;
    }
    if(state)
        ModifyFlagShareBufferDataContent(NULL,CfgOperaType_None,FlagShareBuffer_GenWorkingSta,GenWorkStaOrd_x,OperaOpt);
}

static void StartTestFlow(STARTTYPE type,uint8_t WorkflowMode)
{
    ShareBuffer_ReStartWorkflowMode = WorkflowMode;
    if(type==ManualType)
        ChangeGenWorkingSta(GenWorkStaOrd_ManualStart,BitOperaOpt_Set);
    else
        ChangeGenWorkingSta(GenWorkStaOrd_AutoStart,BitOperaOpt_Set);
}
static uint8_t WithoutOrderHandleRequestWorkLayerHandle(uint8_t TempWorkflow, uint8_t *ActInform)
{
    uint8_t WFAction = DEF_FALSE;
    MOTORTYPE motor;
    MotorAction action;
    float TimeS;
    uint8_t PF;
    int8_t HZ;
    REM_DEVICE_TYPE type=REM_DEVICE_MOTOR;//1-顺逆，2-PF，3-Hz
    switch (share_RemoteDataAddress_st.addr)
    {
    case Addr_DeviceCtlTmp_ProcMode_Swtich:
        switch (share_RemoteDataAddress_st.sourData)
        {
            case CHANGE_TOAutoType:
                // ChangeStartType(AutoType);
                break;
            case CHANGE_TOManualType:
                // ChangeStartType(ManualType);
                break;
        }
    case Addr_DeviceCtlTmp_Control_order:
        /* 1. */
        switch (share_RemoteDataAddress_st.sourData)
        {
        case STOP_TESTFLOW:
            
            break;
        case START_BUILDPRESSURE:
            StartTestFlow(ManualType,WorkflowMode_BuildUpVoltage);
            break;
        case START_VOLATILITY:
            StartTestFlow(ManualType,WorkflowMode_Volatility);
            break;
        case START_EXTEXCITATION:
            StartTestFlow(ManualType,WorkflowMode_ExtExcitation);
            break;
        case START_LOWFREPROTE:
            StartTestFlow(ManualType,WorkflowMode_LowFreProte);
            break;
        case START_STARTSTOP:
            StartTestFlow(ManualType,WorkflowMode_StartStop);
            break;
        case START_CLOSEGATE:
            // StartTestFlow(ManualType,TestFlow_CloseGate);
            break;
        case START_LOADUNLOAD:
            // StartTestFlow(ManualType,TestFlow_LoadUnLoad);
            break;
        case START_TUNING0APF:
            // StartTestFlow(ManualType,TestFlow_Tuning0APF);
            break;
        case START_TUNING08PF:
            // StartTestFlow(ManualType,TestFlow_Tuning08PF);
            break;
        case START_TUNING06A04PF:
            // StartTestFlow(ManualType,TestFlow_Tuning06A04PF);
            break;
        case START_OPENGATE:
            // PID_GeneratorSyncSwitch(PIDSyncAction_Open);
            break;
        case REST_TESTFLOW: 
            ChangeGenWorkingSta(GenWorkStaOrd_AlarmReset,BitOperaOpt_Set);
            break;
        case START_PRIMEMOTOR:
            PidReqPriMoverStartStop(50,8,PriMover_ENUM_Type_Start,12,ShareInOrderSta_PriMoverStart);
            break;
        case STOP_PRIMEMOTOR:
            if(GetFlagShareBufferDataContent(NULL,CfgOperaType_None,FlagShareBuffer_GenWorkingSta,GenWorkStaOrd_Running))
                ModifyFlagShareBufferDataContent(NULL,CfgOperaType_None,FlagShareBuffer_RawAlarm,RawAlarm_EmergencyStop,BitOperaOpt_Set);
            else
                PidReqPriMoverStartStop(0,8,PriMover_ENUM_Type_Stop,12,ShareInOrderSta_PriMoverStop);
            break;
        }
        break;
    case Addr_DeviceCtlTmp_TestProcess_order:
        switch (share_RemoteDataAddress_st.sourData)
        {
       case START_BUILDPRESSURE:
            // StartTestFlow(AutoType,TestFlow_BuildPressure);
            break;
        case START_VOLATILITY:
            // StartTestFlow(AutoType,TestFlow_Volatility);
            break;
        case START_EXTEXCITATION:
            // StartTestFlow(AutoType,TestFlow_ExtExcitation);
            break;
        case START_LOWFREPROTE:
            // StartTestFlow(AutoType,TestFlow_LowFreProte);
            break;
        case START_STARTSTOP:
            // StartTestFlow(AutoType,TestFlow_StartStop);
            break;
        case START_CLOSEGATE:
            // StartTestFlow(AutoType,TestFlow_CloseGate);
            break;
        case START_LOADUNLOAD:
            // StartTestFlow(AutoType,TestFlow_LoadUnLoad);
            break;
        case START_TUNING0APF:
            // StartTestFlow(AutoType,TestFlow_Tuning0APF);
            break;
        case START_TUNING08PF:
            // StartTestFlow(AutoType,TestFlow_Tuning08PF);
            /* code */
            break;
        case START_TUNING06A04PF:
            // StartTestFlow(AutoType,TestFlow_Tuning06A04PF);
            /* code */
            break;
        }
        break;
    case Addr_DeviceCtlTmp_ManualAdjust_order:
        switch (share_RemoteDataAddress_st.sourData>>8)
        {
        case ORD_PHASE_MOTOR:
            break;
        case ORD_EXCV_MOTOR:
            motor=EXCV_MOTOR;
            break;
        case ORD_EXCI_MOTOR:
            motor=EXCI_MOTOR;
            break;
        case ORD_EXCI2_MOTOR:
            motor=EXCI2_MOTOR;
            break;
        case ORD_BUILD_VOL_MOTOR:
            motor=BUILDVOL_MOTOR;
            break;
        case ORD_VOL_PF_MOTOR:
            type=2;
            break;
        case ORD_PRIME_MOTOR:
            type=3;
            break;
        }
        switch (share_RemoteDataAddress_st.sourData&0xFF)
        {
        case ORD_FOR_100:
            switch (type)
            {
            case REM_DEVICE_PF:
                PF=0.05;
                break;
            case REM_DEVICE_HZ:
                HZ=0.1;
                break;
            default:
                TimeS=0.1;
                break;
            }
            action=motorFOR;
            break;
        case ORD_FOR_200:
            switch (type)
            {
            case REM_DEVICE_PF:
                PF=0.1;
                break;
            case REM_DEVICE_HZ:
                //HZ=0.2;
                HZ=1;
                break;
            default:
                TimeS=0.2;
                break;
            }
            action=motorFOR;
            break;
        case ORD_FOR_500:
            switch (type)
            {
            case REM_DEVICE_PF:
                PF=0.2;
                break;
            case REM_DEVICE_HZ:
                HZ=0.5;
                break;
            default:
                TimeS=0.5;
                break;
            }
            action=motorFOR;
            break;
        case ORD_REV_100:
            switch (type)
            {
            case REM_DEVICE_PF:
                PF=0.05;
                break;
            case REM_DEVICE_HZ:
                HZ=0.1;
                break;
            default:
                TimeS=0.1;
                break;
            }
            action=motorREV;
            break;
        case ORD_REV_200:
            switch (type)
            {
            case REM_DEVICE_PF:
                PF=0.1;
                break;
            case REM_DEVICE_HZ:
                //HZ=0.2;
                HZ=-1;
                break;
            default:
                TimeS=0.2;
                break;
            }
            action=motorREV;
            break;
        case ORD_REV_500:
            switch (type)
            {
            case REM_DEVICE_PF:
                PF=0.2;
                break;
            case REM_DEVICE_HZ:
                HZ=0.5;
                break;
            default:
                TimeS=0.5;
                break;
            }
            action=motorREV;
            break;
        }

        switch (type)
        {
        case REM_DEVICE_PF:
            break;
        case REM_DEVICE_HZ:
            PidReqPriMoverStartStop(pMotorStatus_st.curFreq+HZ,5,PriMover_ENUM_Type_Start,5,ShareInOrderSta_PriMoverStart);
            break;           
        default:
            switch (motor)
            {
            case EXCV_MOTOR:
                PidReqExcvSetTime(action,0.5);
                break;
            case BUILDVOL_MOTOR:
                PidReqBVolSetTime(action,0.5);
                break;
            case EXCI_MOTOR:
                PidReqExciSetTime(action,0.5);
                break;
            }
		    
            break;
        }

    }
	return (WFAction);
}
uint8_t temTestFlag;
/* Workflow Layer */
static uint8_t WorkflowInputsLayerHandle(OS_FLAGS os_value)
{
	uint8_t ActInform = DEF_FALSE, WFAction = DEF_FALSE, TempWorkflow;
	uint8_t TempShareOutAlarm[RawAlarm_TOTByteNum];		//工作流程中的告警输出标志组，它既包含了复制的原始告警标志组，又新增各数字输入口的告警级别（警告、停机、跳闸....）标志

	/* Get Raw Alarm 从 FlagShareBuffer_RawAlarm 复制原始告警标志到流程工作的输出告警bit组 TempShareOutAlarm */
  	ExchangeShareBufferDataContent(NULL,CfgOperaType_None,TempShareOutAlarm,FlagShareBuffer_RawAlarm,RawAlarm_TOTByteNum);
  	ExchangeShareBufferDataContent(NULL,CfgOperaType_None,TempShareOutAlarm,FlagShareBuffer_RawAlarm,RawAlarm_TOTByteNum);
	/* Get Workflow */
	TempWorkflow = GetShareBufferDataContent(App_Sem_WORKFLOW, CfgOperaType_OSSem, &ShareBuffer_WorkflowMode);
	/* Limit */
	if (TempWorkflow > WorkflowMode_Maximum)
		TempWorkflow = WorkflowMode_Maximum;

	if (os_value & (OSWORKFLOWFlags_WaveRequest | OSWORKFLOWFlags_SelfTiming40HZ))
		WFAction |= WaveRequestWorkLayerHandle(TempWorkflow, &ActInform);
	if (os_value & (OSWORKFLOWFlags_PIDControlRequest | OSWORKFLOWFlags_SelfTiming40HZ))
		WFAction |= PIDControlRequestWorkLayerHandle(TempWorkflow, &ActInform);
	if (os_value & OSWORKFLOWFlags_WithoutOrderHandleRequest)
		WFAction |= WithoutOrderHandleRequestWorkLayerHandle(TempWorkflow, &ActInform);

    uint8_t os_err;
    if(temTestFlag)
    {
        temTestFlag=0;
        OSFlagPost(App_Flags_WORKFLOW,OSWORKFLOWFlags_WithoutOrderHandleRequest,OS_FLAG_SET, &os_err);
    }

	/************************************/
	/* Workflow Workload--Self Timing */
	if ((os_value & (OSWORKFLOWFlags_SelfTiming10HZ | OSWORKFLOWFlags_ReflashRequest)))
	{
		if (os_value & OSWORKFLOWFlags_SelfTiming10HZ)
			ActInform |= WorkflowTimerCounting(TempWorkflow);

		ActInform |= SelfTimingWFWorkLayerHandle(TempWorkflow,TempShareOutAlarm);
	}

	/* Fix to update Relay Output */
	if (WFAction)
		ActInform |= WorkflowOutRequestBit_RelayOut;

	return (ActInform);
}

void App_Task_WORKFLOW(void *p_arg)
{
	uint8_t os_err, ReqStatus;
	OS_FLAGS os_value;

	(void)p_arg;

	/* RAM Reset */
	PORLocalRAMReset_WORKFLOW();

	OSTimeDlyHMSM(0, 0, 0, 200);

	/* Workflow handling */
	while (DEF_TRUE)
	{
		/*  Wait for State Update output Flags  */
		os_value = OSFlagPend(App_Flags_WORKFLOW,
							  OSWORKFLOWFlags_ALL,
							  OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
							  0,
							  &os_err);
		if (os_err != OS_ERR_NONE)
			SYS_DebugERROR;

		/*  Workload running */
		/* Inform Workflow Task */
		ReqStatus = WorkflowInputsLayerHandle(os_value);
		if (ReqStatus & WorkflowOutRequestBit_RelayOut)
			SetOSFlagsForNewInform(App_Flags_RELAY, OSRelayFlags_UpdRequest);
		if (ReqStatus & WorkflowOutRequestBit_WaveRequest)
		{
			SetOSFlagsForNewInform(App_Flags_WORKFLOW, OSWORKFLOWFlags_WaveRequest);
		}
		if (ReqStatus & WorkflowOutRequestBit_NextMode)
		{
			SetOSFlagsForNewInform(App_Flags_WORKFLOW, OSWORKFLOWFlags_ReflashRequest);
		}
			/* feed WatchDog */
#ifdef ENABLE_WATCHDOG_OPT
		IWDG_ReloadCounter();
#endif
	}
}

#endif